package com.violet.service.app.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.violet.domain.dto.app.AOrderDto;
import com.violet.domain.emuns.OrderStatus;
import com.violet.domain.po.BuyAddress;
import com.violet.domain.po.BuyOrder;
import com.violet.domain.po.BuyProduct;
import com.violet.domain.result.ResultPage;
import com.violet.domain.search.MyPage;
import com.violet.domain.vo.app.AOrderVo;
import com.violet.mapper.BuyAddressMapper;
import com.violet.mapper.BuyOrderMapper;
import com.violet.mapper.BuyProductMapper;
import com.violet.service.app.AWaitPaidOrderService;
import com.violet.utils.MQUtils;
import com.violet.utils.OrderUtils;
import com.violet.utils.TransitionUtils;
import com.violet.utils.UserContent;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AWaitPaidOrderServiceImpl extends ServiceImpl<BuyOrderMapper, BuyOrder>
        implements AWaitPaidOrderService {

    private final OrderUtils orderUtils;

    private final TransitionUtils<AOrderDto, BuyOrder, AOrderVo> orderT;
    private final TransitionUtils<AOrderDto.AOrderProduct, BuyProduct, AOrderVo.AOrderProduct> productT;
    private final TransitionUtils<AOrderDto.AOrderAddress, BuyAddress, AOrderVo.AOrderAddress> addressT;

    private final BuyProductMapper buyProductMapper;
    private final BuyAddressMapper buyAddressMapper;

    private final MQUtils mqUtils;

    @Override
    public ResultPage<List<AOrderVo>> getWaitPayOrders(MyPage myPage) {
        // 拿到分页
        return orderUtils.getOrder(myPage, OrderStatus.WAIT_PAID);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ)
    public Boolean cancelWaitPayOrder(String id) {
        BuyOrder order = baseMapper.getByIdAndUserIdWithPessimisticLock(id, UserContent.getUserId());
        if (order == null) throw new RuntimeException("订单不存在");
        if (order.getStatus() != OrderStatus.WAIT_PAID) throw new RuntimeException("订单状态错误");
        return baseMapper.deleteById(order) == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ)
    public void createWaitPayOrder(AOrderDto dto) {
        // 拿到订单
        BuyOrder buyOrder = orderT.transition(dto, BuyOrder.class)
                .setUserId(UserContent.getUserId())
                .setStatus(OrderStatus.WAIT_PAID);

        // 拿到商品
        List<BuyProduct> products = dto.getProducts().stream()
            .map(item -> {
                // 转 PO
                BuyProduct transition = productT.transition(item, BuyProduct.class);
                // 设置商品 ID
                transition.setProductId(item.getId());
                // 设置订单 ID
                transition.setOrderId(buyOrder.getId());
                // 返回
                return transition;
            }).toList();

        // 拿到地址
        BuyAddress address = addressT.transition(dto.getAddress(), BuyAddress.class)
                .setOrderId(buyOrder.getId());

        // 入库
        try {
            // 先插入订单
            baseMapper.insert(buyOrder);
            // 先插入地址
            buyAddressMapper.insert(address);
            // 插入商品
            buyProductMapper.insert(products);
        }
        catch (Exception e) {throw new RuntimeException("创建订单失败: " + e);}
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ)
    public Boolean payWaitPayOrder(String id) {
        BuyOrder order = baseMapper.getByIdAndUserIdWithPessimisticLock(id, UserContent.getUserId());
        if (order == null) throw new RuntimeException("订单不存在");
        if (order.getStatus() != OrderStatus.WAIT_PAID) throw new RuntimeException("订单状态错误");
        // 1. 更新订单状态 => 待发货
        order.setStatus(OrderStatus.WAIT_DELIVERY);
        // 2. 更新支付时间
        order.setOrderTime(LocalDateTime.now());
        // 3. 数据入库
        if (baseMapper.updateById(order) == 1) {
            // 4. 通知后台准备发货
            // @TODO
            // 发送消息
            mqUtils.sendPaid(order);
            return true;
        }
        return false;
    }

}
